home *** CD-ROM | disk | FTP | other *** search
- /* ContinueTesting.c */
- /*
- * ContinueTesting.c
- * Copyright © 93 Apple Computer Inc. All Rights Reserved.
- *
- * Run the dialog until the user has had enough.
- */
- #include "SCSIAsyncSample.h"
- #include "SCSIDefinitions.h"
- pascal void
- PerformTestIOCompletion(
- void *ioPtr
- );
-
- #define INFO (*infoPtr)
-
- void ComputeTestParameters(
- register InfoPtr infoPtr
- );
- void PerformTest(
- register InfoPtr infoPtr
- );
-
-
-
- void
- StartTesting(void)
- {
- InfoPtr infoPtr;
-
- for (infoPtr = (InfoPtr) infoPtrQueue.qHead;
- infoPtr != NULL;
- infoPtr = (InfoPtr) infoPtr->link) {
- if (INFO.validDevice) {
- INFO.sampleSum = INFO.sampleSumSquare = 0.0;
- INFO.deviceActive = TRUE;
- Microseconds(&INFO.testStartTime);
- if (INFO.enableAsync) {
- /*
- * This loop is entered once when we start the actual test.
- * It is only called for asychronous threads.
- */
- ComputeTestParameters(infoPtr);
- PerformTest(infoPtr);
- }
- }
- }
- }
-
- void
- ContinueTesting(void)
- {
- InfoPtr infoPtr;
- Boolean somethingIsBusy;
- static Boolean stoppedYet = FALSE;
-
- somethingIsBusy = FALSE;
- for (infoPtr = (InfoPtr) infoPtrQueue.qHead;
- infoPtr != NULL;
- infoPtr = (InfoPtr) infoPtr->link) {
- if (INFO.deviceActive && INFO.testCompleted == FALSE) {
- somethingIsBusy = TRUE;
- if (INFO.enableAsync == FALSE) {
- /*
- * This loop is entered each time through the event loop to
- * read one request from a synchronous test thread. It is not
- * called for asychronous threads.
- */
- ComputeTestParameters(infoPtr);
- PerformTest(infoPtr);
- }
- }
- }
- if (somethingIsBusy == FALSE) {
- InitCursor();
- if (stoppedYet == FALSE) {
- stoppedYet = TRUE;
- DisplayTestResults();
- }
- }
- }
-
- void VMStartMarker(void) { }
-
- /*
- * These may be called from an I/O completion routine
- */
- void
- PerformTest(
- register InfoPtr infoPtr
- )
- {
- short commandLength;
- OSErr status;
- register short i;
- register SCSIExecIOPB *pb;
- register RequestMemoryPtr requestMemoryPtr;
- #define PB (*pb)
-
- ClearMemory((Ptr) INFO.vmHoldInfo, sizeof INFO.vmHoldInfo);
- CLEAR(INFO.command);
- if (INFO.transferSizeBlocks <= 256
- && INFO.blockCount <= 0x001FFFFFL) {
- INFO.command.scsi6.opcode = kScsiCmdRead6;
- INFO.command.scsi6.lbn3 = (INFO.blockNumber >> 16) & 0xFF;
- INFO.command.scsi6.lbn2 = (INFO.blockNumber >> 8) & 0xFF;
- INFO.command.scsi6.lbn1 = (INFO.blockNumber ) & 0xFF;
- INFO.command.scsi6.len = INFO.transferSizeBlocks & 0xFF;
- INFO.command.scsi6.lbn3 |= (INFO.deviceIdent.LUN << 5) & 0xE0;
- commandLength = sizeof INFO.command.scsi6;
- }
- else {
- INFO.command.scsi10.opcode = kScsiCmdRead6;
- INFO.command.scsi10.lbn4 = (INFO.blockNumber >> 24) & 0xFF;
- INFO.command.scsi10.lbn3 = (INFO.blockNumber >> 16) & 0xFF;
- INFO.command.scsi10.lbn2 = (INFO.blockNumber >> 8) & 0xFF;
- INFO.command.scsi10.lbn1 = (INFO.blockNumber ) & 0xFF;
- INFO.command.scsi10.len2 = (INFO.transferSizeBlocks >> 8) & 0xFF;
- INFO.command.scsi10.len1 = (INFO.transferSizeBlocks ) & 0xFF;
- INFO.command.scsi10.lun |= (INFO.deviceIdent.LUN << 5) & 0xE0;
- commandLength = sizeof INFO.command.scsi10;
- }
- /*
- * Plug the parameters into the SCSI command block.
- */
- pb = INFO.pb;
- PB.scsiPBLength = INFO.pbSize;
- PB.scsiFunctionCode = SCSIExecIO;
- /*
- * Use the private pointer in the SCSI command block to link the
- * SCSI parameter block to the InfoRecord.
- */
- PB.scsiDriverStorage = (unsigned char *) infoPtr;
- PB.scsiCompletion = (INFO.enableAsync) ? PerformTestIOCompletion : NULL;
- PB.scsiTimeout = INFO.completionTimeout;
- PB.scsiSelectTimeout = INFO.completionTimeout;
- PB.scsiDevice = INFO.deviceIdent;
- PB.scsiCDBLength = commandLength;
- PB.scsiCDB.cdbPtr = (unsigned char *) &INFO.command;
- PB.scsiFlags = (scsiCDBIsPointer | scsiSIMQNoFreeze);
- PB.scsiFlags |= (INFO.enableDisconnect)
- ? scsiDoDisconnect
- : scsiDontDisconnect;
- if (INFO.bufferPtr == NULL || INFO.bufferLength == 0)
- PB.scsiFlags |= scsiDirectionNone;
- else {
- /*
- * If the user specified the transfer quantum == 1, select "polled"
- * transfers, otherwise, select "blind."
- */
- PB.scsiTransferType = (INFO.transferQuantum == 1)
- ? scsiTransferPolled
- : scsiTransferBlind;
- PB.scsiDataPtr = (unsigned char *) INFO.bufferPtr;
- PB.scsiDataLength = INFO.bufferLength;
- PB.scsiDataType = scsiDataBuffer;
- PB.scsiFlags |= scsiDirectionIn;
- PB.scsiHandshake[0] = 512;
- PB.scsiHandshake[1] = 0;
-
- }
- INFO.senseData.errorCode = 0;
- PB.scsiSensePtr = (unsigned char *) &INFO.senseData;
- PB.scsiSenseLength = sizeof INFO.senseData;
- if (gVirtualMemoryEnabled) {
- /* Function */
- /* Param block */
- INFO.vmHoldInfo[kVMParam].ptr = INFO.pb;
- INFO.vmHoldInfo[kVMParam].size = INFO.pbSize;
- /* Data buffer */
- INFO.vmHoldInfo[kVMBuffer].ptr = PB.scsiDataPtr;
- INFO.vmHoldInfo[kVMBuffer].size = PB.scsiDataLength;
- /* Info record (has command and sense buffer) */
- INFO.vmHoldInfo[kVMSense].ptr = PB.scsiSensePtr;
- INFO.vmHoldInfo[kVMSense].size = PB.scsiSenseLength;
- for (i = 0; i < kVMSize; i++) {
- if (INFO.vmHoldInfo[i].ptr != NULL) {
- status = HoldMemory(
- INFO.vmHoldInfo[i].ptr,
- INFO.vmHoldInfo[i].size
- );
- if (status != noErr) {
- while (i < kVMSize)
- INFO.vmHoldInfo[i++].ptr = NULL;
- break;
- }
- }
- }
- if (status != noErr) {
- /*
- * Something failed. Unwind before exiting.
- */
- for (i = 0; i < kVMSize; i++) {
- if (INFO.vmHoldInfo[i].ptr != NULL) {
- (void) UnholdMemory(
- INFO.vmHoldInfo[i].ptr,
- INFO.vmHoldInfo[i].size
- );
- }
- }
- }
- }
- /*
- * What ho, here we go!
- */
- requestMemoryPtr = &INFO.requestMemory[INFO.transfersAttempted % kRequestMemory];
- INFO.requestMemoryPtr = requestMemoryPtr;
- requestMemoryPtr->blockNumber = INFO.blockNumber;
- ++INFO.transfersAttempted;
- Microseconds(&requestMemoryPtr->startTime);
- status = SCSIAction((SCSI_PB *) pb);
- if (PB.scsiResult == scsiRequestInProgress)
- ++INFO.asynchRequests;
- if (status != noErr) {
- if (PB.scsiCompletion == NULL && PB.scsiResult == noErr)
- PB.scsiResult = status;
- if (INFO.finalStatus == noErr)
- INFO.finalStatus = status;
- }
- /*
- * If we're asychronous, just exit - the I/O completion routine will
- * clean up the mess. If we're synchronous, we're done, so call the
- * I/O completion routine ourself.
- */
- if (PB.scsiCompletion == NULL)
- PerformTestIOCompletion(pb);
- }
-
- /*
- * This is called by I/O completion.
- */
- pascal void
- PerformTestIOCompletion(
- void *ioPtr
- )
- {
- register SCSIExecIOPB *pb;
- register InfoPtr infoPtr;
- short i;
- double sampleTime;
- UnsignedWide difference;
-
- pb = (SCSIExecIOPB *) ioPtr;
- infoPtr = (InfoPtr) PB.scsiDriverStorage;
- Microseconds(&INFO.requestMemoryPtr->endTime);
- MicrosecondDelta(
- &INFO.requestMemoryPtr->startTime,
- &INFO.requestMemoryPtr->endTime,
- &difference
- );
- sampleTime = MicrosecondToDouble(&difference) / 1000000.0;
- INFO.sampleSum += sampleTime;
- INFO.sampleSumSquare += (sampleTime * sampleTime);
- /*
- * Release virtual memory
- */
- for (i = 0; i < kVMSize; i++) {
- if (INFO.vmHoldInfo[i].ptr != NULL) {
- (void) UnholdMemory(
- INFO.vmHoldInfo[i].ptr,
- INFO.vmHoldInfo[i].size
- );
- }
- }
- ++INFO.transfersCompleted;
- /*
- * If an error occurred, set the global "stop" flag to prevent
- * errors from cascading.
- */
- if (PB.scsiResult != noErr && INFO.finalStatus == noErr)
- INFO.finalStatus = PB.scsiResult;
- if (INFO.finalStatus != noErr)
- INFO.testCompleted = TRUE;
- else if (INFO.totalTransfers != 0
- && INFO.transfersCompleted >= INFO.totalTransfers)
- INFO.testCompleted = TRUE;
- /*
- * If we're running asychronously and are still alive, start the
- * next transfer.
- */
- if (INFO.testCompleted) {
- INFO.testEndTime = INFO.requestMemoryPtr->endTime;
- INFO.deviceActive = FALSE;
- }
- else if (INFO.enableAsync) {
- ComputeTestParameters(infoPtr);
- PerformTest(infoPtr);
- }
- }
-
- void VMEndMarker(void) { }
-
- void
- ComputeTestParameters(
- register InfoPtr infoPtr
- )
- {
- if (INFO.finalStatus != noErr
- || (INFO.totalTransfers != 0
- && INFO.transfersCompleted >= INFO.totalTransfers))
- INFO.testCompleted = TRUE;
- else if (INFO.enableRandomSeek) {
- INFO.randomSeed = (INFO.randomSeed * 1103515245L) + 12345L;
- INFO.nextBlockNumber = INFO.randomSeed % INFO.totalLogicalBlocks;
- goto computeByteCount;
- }
- else {
- if (INFO.nextBlockNumber >= INFO.totalLogicalBlocks)
- INFO.nextBlockNumber = 0;
- computeByteCount:
- INFO.blockNumber = INFO.nextBlockNumber;
- INFO.blockCount = INFO.transferSizeBlocks;
- if (INFO.blockNumber + INFO.blockCount >= INFO.totalLogicalBlocks)
- INFO.blockCount = INFO.totalLogicalBlocks - INFO.blockNumber;
- INFO.byteCount = INFO.transferSizeBlocks * INFO.logicalBlockLength;
- INFO.nextBlockNumber = INFO.blockNumber + INFO.blockCount;
- }
- }
-
-